


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

/**
 * This thread handles incoming messages from the server. It handles confirmations for
 * send measures and orders (shutdown, reboot) received by the administrator.
 *
 * @author Alexandre Dos Santos Coelho
 */
public class InputThread extends Thread {

  private int confirm; // Number of confirmations received
  private boolean running = true; // Determines if the thread is running or not
  private Socket socket; // Communication socket from the attached CommunicationThread
  private CommunicationThread communicationThread; // attached CommunicationThread
  BufferedReader in; // Incoming communication channel

  /**
   * Contructor. Creates a new incoming messages handler thread.
   *
   * @param s socket from attached CommunicationThread
   * @param ct attached CommunicationThread
   */
  public InputThread(Socket s, CommunicationThread ct) {
    socket = s;
    communicationThread = ct;
    try {
      in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    } catch (IOException ex) {
      System.err.println(Logger.getTime() + "Impossible to open input channel");
    }
  }

  /**
   * Thread run method. This method receives messages from the server. It can receive two types
   * of messages:
   * <ul>
   *  <li>Measure reception confirmation
   *  <li>Order (shutdown, reboot)
   * </ul>
   */
  public void run() {
    while (isRunning()) {
      try {
        String input = in.readLine();
        // Detecting server crash (when input is null)
        if (input == null || !input.split("#")[1].equals("ok")) {
          running = false;
          communicationThread.setRunning(false);
          communicationThread.setConnected(false);
        }
        String[] data = input.split("#");
        // Received an order
        if (data[0].equals("order")) {
          if (data[1].equals("shutdown")) {
            System.out.println(Logger.getTime() + "Received shutdown order.");
            Runtime.getRuntime().exec("shutdown -s -t 0");
          } else if(data[1].equals("reboot")) {
            System.out.println(Logger.getTime() + "Received reboot order.");
            Runtime.getRuntime().exec("shutdown -r");
          }
        } else if (data[0].equals("measure") && data[1].equals("ok")) { // Received confirmation
          communicationThread.removeMeasure(Integer.valueOf(data[2]));
          setConfirm(getConfirm() + 1);
        }

      } catch (IOException ex) {
        running = false;
        communicationThread.setRunning(false);
        communicationThread.setConnected(false);
      } catch (NullPointerException ex) {
        running = false;
        communicationThread.setRunning(false);
        communicationThread.setConnected(false);
      }
    }

  }

  /**
   * @return The number of confimations received
   */
  public int getConfirm() {
    return confirm;
  }

  /**
   * @param confirm The number of confirmation received
   */
  public void setConfirm(int confirm) {
    this.confirm = confirm;
  }

  /**
   * @return If the thread is running
   */
  public boolean isRunning() {
    return running;
  }

  /**
   * @param running Change thread running state
   */
  public void setRunning(boolean running) {
    this.running = running;
  }
}